package com.inoneone.youba.mcht.controller;

import com.inoneone.toolkit.enums.EventType;
import com.inoneone.toolkit.enums.MchtStatus;
import com.inoneone.toolkit.exception.AssertUtil;
import com.inoneone.toolkit.exception.BusinessRuntimeException;
import com.inoneone.toolkit.exception.RegExp;
import com.inoneone.youba.mcht.cache.mapper.MobileIntervalMapper;
import com.inoneone.youba.mcht.cache.mapper.ModifyPwdMapper;
import com.inoneone.youba.mcht.cache.mapper.VerifyCodeMapper;
import com.inoneone.youba.mcht.cache.po.MobileIntervalPo;
import com.inoneone.youba.mcht.cache.po.ModifyPwdPo;
import com.inoneone.youba.mcht.cache.po.ResetPwdPo;
import com.inoneone.youba.mcht.cache.po.VerifyCodePo;
import com.inoneone.youba.mcht.conf.ValueConfig;
import com.inoneone.youba.mcht.dao.po.Merchant;
import com.inoneone.youba.mcht.dto.BaseRsp;
import com.inoneone.youba.mcht.dto.PageRsp;
import com.inoneone.youba.mcht.dto.req.*;
import com.inoneone.youba.mcht.dto.rsp.ChangePwdPrepareRsp;
import com.inoneone.youba.mcht.dto.rsp.FindPayPwdPrepareRsp;
import com.inoneone.youba.mcht.dto.rsp.MyEventRsp;
import com.inoneone.youba.mcht.enums.Constants;
import com.inoneone.youba.mcht.enums.ErrorCode;
import com.inoneone.youba.mcht.enums.ResetPwdStep;
import com.inoneone.youba.mcht.pojo.Event;
import com.inoneone.youba.mcht.service.MerchantApi;
import com.inoneone.youba.mcht.service.MsgCenterApi;
import com.inoneone.youba.mcht.service.SafeApi;
import com.inoneone.youba.mcht.util.CommonUtil;
import com.inoneone.youba.mcht.util.DateUtil;
import com.inoneone.youba.mcht.util.StringUtil;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.*;

import javax.servlet.http.HttpSession;
import java.util.Calendar;
import java.util.Date;


@RestController
@RequestMapping(value = "/safe", method = {RequestMethod.POST})
public class SafeController {
	@Autowired
	private SafeApi safeApi;

    @Autowired
    private MerchantApi merchantApi;

    @Autowired
    private MsgCenterApi msgCenterApi;

    @Autowired
    private VerifyCodeMapper verifyCodeMapper;

    @Autowired
    private MobileIntervalMapper mobileIntervalMapper;

    @Autowired
    private ValueConfig valueConfig;

    @Autowired
    private ModifyPwdMapper modifyPwdMapper;

    /**
     * Description: 查询系统事件</br>
     * Date: 2017-06-28 13:37:48</br>
     *
     * @param
     * @return
     * @author 姬远玄
     * @since JDK 1.7
    */
    @PostMapping(value = "/myEvent")
    @ResponseBody
    public Object myEvent(HttpSession httpSession, @RequestBody MyEventReq myEventReq) {
        //参数检查
        myEventReq.validate();

        if(!CommonUtil.isNullOrEmpty(myEventReq.getKeywords()))
        {
            AssertUtil.hasText(myEventReq.getKeywords(), ErrorCode.CARD);

        }
        if(myEventReq.getType() != null)
        {
            AssertUtil.isBetween(myEventReq.getType(), 1, 12, ErrorCode.EVENT_TYPE);
        }

        if(myEventReq.getBeginTime() != 0)
        {
            AssertUtil.isBetween(myEventReq.getBeginTime(), Constants.DATETIME_BEGIN, Constants.DATETIME_END, ErrorCode.DATE_TIME);

        }
        if(myEventReq.getEndTime() != 0)
        {
            AssertUtil.isBetween(myEventReq.getEndTime(), Constants.DATETIME_BEGIN, Constants.DATETIME_END, ErrorCode.DATE_TIME);
        }

        //获取session
        Merchant merchant = CommonUtil.getSession(httpSession);

        //查询订单
        PageRsp<MyEventRsp> pageInfo = safeApi.querySysEvent(myEventReq, merchant.getId());

        //返回
        return new BaseRsp(pageInfo);
    }

    @PostMapping(value = "/myEventPlus")
    @ResponseBody
    public Object myEventPlus(HttpSession httpSession, @RequestBody MyEventPlusReq myEventPlusReq) {

        MyEventReq myEventReq = new MyEventReq();
        if(!CommonUtil.isNullOrEmpty(myEventPlusReq.getMonth()))
        {
            AssertUtil.isMatch(myEventPlusReq.getMonth(), RegExp.YYYYMM, ErrorCode.DATE);

            //年月
            Date month = DateUtil.parseDate(myEventPlusReq.getMonth(), "yyyy-MM");
            Calendar calendar = Calendar.getInstance();
            calendar.setTime(month);
            calendar.set(Calendar.DAY_OF_MONTH, 1);

            //开始时间
            myEventReq.setBeginTime(calendar.getTime().getTime());

            //结束时间
            calendar.roll(Calendar.DAY_OF_MONTH, -1);
            myEventReq.setEndTime(calendar.getTime().getTime());

        }
        BeanUtils.copyProperties(myEventPlusReq, myEventReq);

        return myEvent(httpSession, myEventReq);
    }

    /**
     * 手机端修改密码
     * @param httpSession
     * @param changePwdPrepareReq
     * @return
     */
    @PostMapping(value = "/changePwdPrepare")
    @ResponseBody
    public Object changePwdPrepare(HttpSession httpSession, @RequestBody ChangePwdPrepareReq changePwdPrepareReq) {
        //参数检查
        AssertUtil.hasText(changePwdPrepareReq.getOldPassword(), 32, ErrorCode.PASSWORD_BAD);


        //获取session
        Merchant merchant = CommonUtil.getSession(httpSession);

        //检查用户状态
        if(merchant.getStatus() != MchtStatus.NOMAL.getCode())
        {
            throw new BusinessRuntimeException(ErrorCode.MCH_BAD_STATUS);

        }

        //校验密码
        if(!changePwdPrepareReq.getOldPassword().equals(merchant.getPassword()))
        {
            throw new BusinessRuntimeException(ErrorCode.PASSWORD_WRONG);
        }

        //生成操作session
        ModifyPwdPo modifyPwdPo = new ModifyPwdPo();
        modifyPwdPo.setSessionId(CommonUtil.genRandomKey());
        modifyPwdPo.setSessionTime(System.currentTimeMillis());
        modifyPwdMapper.insertAndUpdate(modifyPwdPo);

        ChangePwdPrepareRsp changePwdPrepareRsp = new ChangePwdPrepareRsp();
        changePwdPrepareRsp.setSessionId(modifyPwdPo.getSessionId());
        //返回
        return new BaseRsp(changePwdPrepareRsp);
    }

    /**
     * 手机端修改密码
     * @param httpSession
     * @param changePwdReq
     * @return
     */
    @PostMapping(value = "/changePwd")
    @ResponseBody
    public Object changePwd(HttpSession httpSession, @RequestBody ChangePwdReq changePwdReq) {
        //参数检查
        AssertUtil.isMatch(changePwdReq.getSessionId(), RegExp.VERIFY_SESSIONID, ErrorCode.VERIFY_SESSIONID);
        AssertUtil.hasText(changePwdReq.getSessionId(), 32, ErrorCode.NEW_PASSWORD_BAD);

        //获取session
        Merchant merchant = CommonUtil.getSession(httpSession);

        //检查用户状态
        if(merchant.getStatus() != MchtStatus.NOMAL.getCode())
        {
            throw new BusinessRuntimeException(ErrorCode.MCH_BAD_STATUS);

        }

        //校验原密码和现密码是否相同
        if(merchant.getPassword().equals(changePwdReq.getNewPassword()))
        {
            throw new BusinessRuntimeException(ErrorCode.SAME_PWD);
        }

        //校验session
        ModifyPwdPo modifyPwdPo = modifyPwdMapper.select(changePwdReq.getSessionId());
        if(modifyPwdPo == null || modifyPwdPo.getSessionTime() + valueConfig.getVerifyExpireSec() * 1000 < System.currentTimeMillis())
        {
            throw new BusinessRuntimeException(ErrorCode.FAIL_SESSION);
        }

        //更新新密码
        safeApi.modifyPassword(changePwdReq.getNewPassword(), merchant.getId());
        merchant.setPassword(changePwdReq.getNewPassword());
        CommonUtil.setSession(httpSession, merchant);

        //记录日志
        Event event = new Event();
        event.setType(EventType.PWD.getCode());
        event.setDesc("修改登录密码");
        event.setMchId(merchant.getId());
        event.setMchName(merchant.getMchName());
        safeApi.log(event);

        //返回
        return new BaseRsp();
    }

    @PostMapping(value = "/changePassword")
    @ResponseBody
    public Object changePassword(HttpSession httpSession, @RequestBody ChangePasswordReq changePasswordReq) {
        //参数检查
        AssertUtil.hasText(changePasswordReq.getOldPassword(), 32, ErrorCode.PASSWORD_BAD);
        AssertUtil.hasText(changePasswordReq.getNewPassword(), 32, ErrorCode.NEW_PASSWORD_BAD);

        //校验原密码和现密码是否相同
        if(changePasswordReq.getOldPassword().equals(changePasswordReq.getNewPassword()))
        {
            throw new BusinessRuntimeException(ErrorCode.SAME_PWD);
        }

        //获取session
        Merchant merchant = CommonUtil.getSession(httpSession);

        //检查用户状态
        if(merchant.getStatus() != MchtStatus.NOMAL.getCode())
        {
            throw new BusinessRuntimeException(ErrorCode.MCH_BAD_STATUS);

        }

        //校验密码
        if(!changePasswordReq.getOldPassword().equals(merchant.getPassword()))
        {
            throw new BusinessRuntimeException(ErrorCode.PASSWORD_WRONG);
        }

        //更新新密码
        safeApi.modifyPassword(changePasswordReq.getNewPassword(), merchant.getId());
        merchant.setPassword(changePasswordReq.getNewPassword());
        CommonUtil.setSession(httpSession, merchant);

        //记录日志
        Event event = new Event();
        event.setType(EventType.PWD.getCode());
        event.setDesc("修改登录密码");
        event.setMchId(merchant.getId());
        event.setMchName(merchant.getMchName());
        safeApi.log(event);

        //返回
        return new BaseRsp();
    }

    @PostMapping(value = "/changePayPassword")
    @ResponseBody
    public Object changePayPassword(HttpSession httpSession, @RequestBody ChangePasswordReq changePasswordReq) {
        //参数检查
        AssertUtil.hasText(changePasswordReq.getOldPassword(), 32, ErrorCode.PASSWORD_BAD);
        AssertUtil.hasText(changePasswordReq.getNewPassword(), 32, ErrorCode.NEW_PASSWORD_BAD);

        //校验原密码和现密码是否相同
        if(changePasswordReq.getOldPassword().equals(changePasswordReq.getNewPassword()))
        {
            throw new BusinessRuntimeException(ErrorCode.SAME_PWD);
        }


        //获取session
        Merchant merchant = CommonUtil.getSession(httpSession);

        //校验设置的支付密码和登录密码是否相同
        if(changePasswordReq.getNewPassword().equals(merchant.getPassword()))
        {
            throw new BusinessRuntimeException(ErrorCode.SAME_PWD_PAY_PWD);
        }

        //校验原密码是否正确
        if(!changePasswordReq.getOldPassword().equals(merchant.getPayPassword()))
        {
            throw new BusinessRuntimeException(ErrorCode.PASSWORD_WRONG);
        }

        //更新新密码
        safeApi.modifyPayPassword(changePasswordReq.getNewPassword(), merchant.getId());
        merchant.setPayPassword(changePasswordReq.getNewPassword());
        CommonUtil.setSession(httpSession, merchant);

        //记录日志
        Event event = new Event();
        event.setType(EventType.PWD.getCode());
        event.setDesc("修改支付密码");
        event.setMchId(merchant.getId());
        event.setMchName(merchant.getMchName());
        safeApi.log(event);

        //返回
        return new BaseRsp();
    }

    @PostMapping(value = "/findPayPwdPrepare")
    @ResponseBody
    public Object findPayPwdPrepare(HttpSession httpSession) {
        //参数检查

        //获取session
        Merchant merchant = CommonUtil.getSession(httpSession);

        //校验发送间隔
        MobileIntervalPo mobileIntervalPo = mobileIntervalMapper.select(Constants.FIND_PAY_PWD + merchant.getMobile());
        if(System.currentTimeMillis() < mobileIntervalPo.getSendTime() + valueConfig.getMobileIntervalSec() * 1000)
        {
            throw new BusinessRuntimeException(ErrorCode.MOIBLE_INTERVAL);
        }

        //生成verifycode
        VerifyCodePo verifyCodePo = new VerifyCodePo();
        verifyCodePo.setVerifySessionId(CommonUtil.genRandomKey());
        verifyCodePo.setVerifyCode(CommonUtil.genRandom(true, 6));
        verifyCodePo.setMobile(merchant.getMobile());
        verifyCodePo.setInitTime(System.currentTimeMillis());

        //缓存数据
        verifyCodeMapper.insertAndUpdate(verifyCodePo);

        //发送短信
        msgCenterApi.sendVerifyPayPwd(merchant.getMobile(), verifyCodePo.getVerifyCode());
        FindPayPwdPrepareRsp findPayPwdPrepareRsp = new FindPayPwdPrepareRsp();
        findPayPwdPrepareRsp.setVerifySessionId(verifyCodePo.getVerifySessionId());
        findPayPwdPrepareRsp.setMobile(StringUtil.getHiddenMoile(merchant.getMobile()));

        //记录发送时间
        MobileIntervalPo mobileIntervalPoUpdate = new MobileIntervalPo();
        mobileIntervalPoUpdate.setBusinessMobile(Constants.FIND_PAY_PWD + merchant.getMobile());
        mobileIntervalPoUpdate.setSendTime(System.currentTimeMillis());
        mobileIntervalMapper.insertAndUpdate(mobileIntervalPoUpdate);

        //设置步骤

        //返回
        return new BaseRsp(findPayPwdPrepareRsp);
    }

    @PostMapping(value = "/findPayPwd")
    @ResponseBody
    public Object findPayPwd(HttpSession httpSession, @RequestBody FindPayPwdReq findPayPwdReq) {
        //参数检查
        AssertUtil.isMatch(findPayPwdReq.getVerifySessionId(), RegExp.VERIFY_SESSIONID, ErrorCode.VERIFY_SESSIONID);
        AssertUtil.isMatch(findPayPwdReq.getVerifyCode(), RegExp.SMS_VER_CODE, ErrorCode.VERIFY_CODE);
        AssertUtil.hasText(findPayPwdReq.getNewPassword(), 32, ErrorCode.PASSWORD_BAD);

        //获取session
        Merchant merchant = CommonUtil.getSession(httpSession);

        //校验设置的支付密码和登录密码是否相同
        if(findPayPwdReq.getNewPassword().equals(merchant.getPassword()))
        {
            throw new BusinessRuntimeException(ErrorCode.SAME_PWD_PAY_PWD);
        }

        //验证短信
        msgCenterApi.verifySms(findPayPwdReq.getVerifySessionId(), findPayPwdReq.getVerifyCode());

        //更新密码
        safeApi.modifyPayPassword(findPayPwdReq.getNewPassword(), merchant.getId());
        merchant.setPayPassword(findPayPwdReq.getNewPassword());
        CommonUtil.setSession(httpSession, merchant);

        //记录日志
        Event event = new Event();
        event.setType(EventType.PWD.getCode());
        event.setDesc("找回支付密码");
        event.setMchId(merchant.getId());
        event.setMchName(merchant.getMchName());
        safeApi.log(event);

        //返回
        return new BaseRsp();
    }

    /**
     * 手机端发送短信验证码校验
     * @param httpSession
     * @return
     */
    @PostMapping(value = "/findPayPwdTwo")
    @ResponseBody
    public Object findPayPwdTwo(HttpSession httpSession, @RequestBody FindPayPwdTwoReq findPayPwdTwoReq) {
        //参数检查
        AssertUtil.isMatch(findPayPwdTwoReq.getVerifySessionId(), RegExp.VERIFY_SESSIONID, ErrorCode.VERIFY_SESSIONID);
        AssertUtil.isMatch(findPayPwdTwoReq.getVerifyCode(), RegExp.SMS_VER_CODE, ErrorCode.VERIFY_CODE);

        //获取session
        Merchant merchant = CommonUtil.getSession(httpSession);

        //获取缓存验证信息
        VerifyCodePo verifyCodePo = verifyCodeMapper.select(findPayPwdTwoReq.getVerifySessionId());

        //检查step是否为1
        if (verifyCodePo.getStep() != ResetPwdStep.VERIFY_CODE.getCode()) {
            throw new BusinessRuntimeException(ErrorCode.VERIFY_ERR);
        }

        //验证短信
        msgCenterApi.verifySms(findPayPwdTwoReq.getVerifySessionId(), findPayPwdTwoReq.getVerifyCode());

        //设置为下一步
        verifyCodePo.setStep(ResetPwdStep.RESET.getCode());
        verifyCodeMapper.insertAndUpdate(verifyCodePo);

        //返回
        return new BaseRsp();
    }

    /**
     * 手机端发送短信验证码最后更改
     * @param httpSession
     * @return
     */
    @PostMapping(value = "/findPayPwdThree")
    @ResponseBody
    public Object findPayPwdThree(HttpSession httpSession, @RequestBody FindPayPwdThreeReq findPayPwdThreeReq) {
        //参数检查
        AssertUtil.isMatch(findPayPwdThreeReq.getVerifySessionId(), RegExp.VERIFY_SESSIONID, ErrorCode.VERIFY_SESSIONID);
        AssertUtil.hasText(findPayPwdThreeReq.getNewPassword(), 32, ErrorCode.PASSWORD_BAD);

        //获取session
        Merchant merchant = CommonUtil.getSession(httpSession);

        //校验设置的支付密码和登录密码是否相同
        if(findPayPwdThreeReq.getNewPassword().equals(merchant.getPassword()))
        {
            throw new BusinessRuntimeException(ErrorCode.SAME_PWD_PAY_PWD);
        }

        //TODO  校验过期时间

        //获取缓存验证信息
        VerifyCodePo verifyCodePo = verifyCodeMapper.select(findPayPwdThreeReq.getVerifySessionId());

        //检查step是否为3
        if (verifyCodePo == null || verifyCodePo.getStep() != ResetPwdStep.RESET.getCode()) {
            throw new BusinessRuntimeException(ErrorCode.VERIFY_ERR);
        }

        //更新密码
        safeApi.modifyPayPassword(findPayPwdThreeReq.getNewPassword(), merchant.getId());
        merchant.setPayPassword(findPayPwdThreeReq.getNewPassword());
        CommonUtil.setSession(httpSession, merchant);

        //删除验证session
        verifyCodeMapper.delete(findPayPwdThreeReq.getVerifySessionId());

        //记录日志
        Event event = new Event();
        event.setType(EventType.PWD.getCode());
        event.setDesc("找回支付密码");
        event.setMchId(merchant.getId());
        event.setMchName(merchant.getMchName());
        safeApi.log(event);

        //返回
        return new BaseRsp();
    }
}
